package com.xia.demo.lock;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * 线程   操作   资源类
 */
class MyCache{//资源类
    //模拟缓存 volatile可见性
    private volatile Map<String ,Object> map= new HashMap<>();
    private ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();

    //private ReentrantLock lock = new ReentrantLock();
    //传统的锁不足以满足多个线程读，ReentrantLock只能一个线程操作读或者写

    public void put(String key,Object value){
        rwLock.writeLock().lock();
        try{
            System.out.println("线程"+Thread.currentThread().getName()+"\t 正在写入"+key);
            try{TimeUnit.MILLISECONDS.sleep(300);}catch(Exception e){e.printStackTrace();}
            map.put(key,value);
            System.out.println("线程"+Thread.currentThread().getName()+"\t 写入完成");
        }catch(Exception e){
            e.printStackTrace();
        }finally{
            rwLock.writeLock().unlock();
        }
    }
    //读共享且时间段不一样
    public void get(String key){
        rwLock.readLock().lock();
        try{
            System.out.println("线程"+Thread.currentThread().getName()+"\t 正在读取");
            map.get(key);
            System.out.println("线程"+Thread.currentThread().getName()+"\t 读取完成");
        }catch(Exception e){
            e.printStackTrace();
        }finally{
            rwLock.readLock().unlock();
        }
    }

}

/**
 * 多个线程同时读一个资源类没有任何问题，所以为了满足并发量，读取共享资源应该可以同时进行。
 * 但是
 * 如果有一个线程想去写共享资源类，就不应该再有其他线程可以对该资源进行读或写
 * 小总结：
 *      读-读共存
 *      读-写共存
 *      写-写不共存
 *
 *      写操作：原子+独占,整个过程必须是一个完整的统一体，中间不许被分割，被打断
 *
 */
public class ReadWriteLockDemo {
    public static void main(String[] args) {
        MyCache myCache = new MyCache();
        for (int i=0;i<5;i++){
            final int temp = i;
            new Thread(()->{
                myCache.put(temp+"",temp+"");
            },String.valueOf(i)).start();
        }
        for (int i=0;i<5;i++){
            final int temp = i;
            new Thread(()->{
                myCache.get(temp+"");
            },String.valueOf(i)).start();
        }

    }
}